package com.ruoyi.system.interAttr.attr;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.utils.AESUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.interAttr.domain.GamesRes;
import com.ruoyi.system.interAttr.domain.InterAttrRes;
import com.ruoyi.system.interAttr.domain.InterServerRes;
import com.ruoyi.system.model.domain.SalePartner;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;

/**
 * 起飞属性匹配
 *
 * @author ruoyi
 * @data 2024/7/3
 * @apiNote
 */
@Service
@Slf4j
public class NiGuangAttr implements AdapterAttr {
    /**
     * saleKey    -----> appSecret
     * other      -----> appID
     * twoOther   -----> salt
     */
    private String appID = "0SQ53HNZR1FXOPTE"; // 应用ID
    private String appSecret = "11D7D9E4BCD32883C53B5AA158604A96"; // 密钥
    private String salt = "KJ8B1NYPSIX0M3TO"; // 加密盐
    private Integer debug = 0; // 0:签名并加密 1:只签名
    private final Integer timeout = 50000;// 超时，毫秒
    private final String userAgent = "com.ng8866.cooperative.sdk";

    // 测试环境
//    static final String BASE_URL = "https://api.dev.ng8877.com/v2/third/api/cooperative/";
    // 正式环境
    static final String BASE_URL = "https://third-api.ng8866.com/v2/third/api/cooperative/";

    public static void main(String[] args) {
        NiGuangAttr niGuangAttr = new NiGuangAttr();
        TreeMap<String, Object> obj = new TreeMap<>();
        obj.put("test", "我们");
        obj.put("attr_obj", "我2们");
        List<Map<String, Object>> attr_obj = new ArrayList<>();
        attr_obj.add(obj);
        TreeMap<String, Object> params = new TreeMap<>();
        params.put("test", "我们");
        params.put("attr_obj", attr_obj);
        String testStr = niGuangAttr.post("test", params, null);
        System.out.println(testStr);
    }

    /**
     * 获取游戏列表
     *
     * @return
     */
    @Override
    public List<GamesRes> getGames(SalePartner salePartner) {
        String url = "https://www.wmsy.mobi/v2/pc/api/Home/get_game_all";
        HttpResponse execute = HttpRequest.post(url)
                .header("Accept", "application/json, text/plain, */*")
                .header("Accept-Language", "zh-CN,zh;q=0.9")
                .header("Connection", "keep-alive")
                .header("Content-Type", "application/json;charset=UTF-8")
                .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like " +
                        "Gecko) Chrome / 122.0 .0 .0 Safari / 537.36 ")
                .execute();
        String response = execute.body();
        JSONObject responseJson = JSONObject.parseObject(response);
        List<JSONObject> array = JSONObject.parseArray(responseJson.getString("data"), JSONObject.class);
        List<GamesRes> gamesResList = new ArrayList<>();

        for (JSONObject game : array) {
            GamesRes gamesRes = new GamesRes();
            gamesRes.setId(game.getString("id"));
            gamesRes.setGameName(game.getString("game_name"));
            gamesResList.add(gamesRes);
        }
        return gamesResList;
    }

    /**
     * 获取游戏区服列表
     *
     * @return
     */
    @Override
    public List<InterServerRes> getServer(String gameId, SalePartner salePartner) {
        List<InterServerRes> resultList = new ArrayList<>();
        TreeMap<String, Object> action = new TreeMap<>();
        action.put("game_id", gameId);
        String game_goods_attr = post("game_goods_attr", action, salePartner);
        JSONObject jsonObject = JSONObject.parseObject(game_goods_attr).getJSONObject("data");
        List<JSONObject> data_obj = JSONObject.parseArray(jsonObject.getString("data_obj"), JSONObject.class);
        jsonObject.put("data_obj", data_obj);
        System.err.println(jsonObject.toJSONString());
        // 一级区服
        for (JSONObject object : data_obj) {
            InterServerRes interServerRes = new InterServerRes();
            interServerRes.setId(object.getString("id") + "&" + object.getString("name"));
            interServerRes.setName(object.getString("value"));
            // 二级区服
            List<InterServerRes> childrenList = new ArrayList<>();
            List<JSONObject> children = JSONObject.parseArray(object.getString("children"), JSONObject.class);
            if (ObjectUtil.isNotEmpty(children)) {
                for (JSONObject child : children) {
                    InterServerRes childrenRes = new InterServerRes();
                    childrenRes.setId(child.getString("id") + "&" + child.getString("name"));
                    childrenRes.setName(child.getString("value"));
                    // 三级区服
                    List<InterServerRes> lastChildrenList = new ArrayList<>();
                    List<JSONObject> lastChildren = JSONObject.parseArray(child.getString("children"), JSONObject.class);
                    if (ObjectUtil.isNotEmpty(lastChildren)) {
                        for (JSONObject lastChild : lastChildren) {
                            InterServerRes lastChildrenRes = new InterServerRes();
                            lastChildrenRes.setId(lastChild.getString("id") + "&" + lastChild.getString("name"));
                            lastChildrenRes.setName(lastChild.getString("value"));
                            lastChildrenList.add(lastChildrenRes);
                        }
                        childrenRes.setInterServerRes(lastChildrenList);
                    }
                    childrenList.add(childrenRes);
                }
                interServerRes.setInterServerRes(childrenList);
            }
            // 87是英雄联盟端游id
            if (gameId.equals("87")) {
                resultList = interServerRes.getInterServerRes();
            } else {
                resultList.add(interServerRes);
            }
        }
        return resultList;
    }

    /**
     * 获取游戏属性列表
     *
     * @return
     */
    @Override
    public List<InterAttrRes> getPropety(String gameId, String type, SalePartner salePartner) {
        type = StringUtils.equals(type, "1") ? "radio" : StringUtils.equals(type, "2") ? "select" : "input_num,input_text";
        List<InterAttrRes> resultList = new ArrayList<>();
        TreeMap<String, Object> action = new TreeMap<>();
        action.put("game_id", gameId);
        String game_goods_attr = post("game_goods_attr", action, salePartner);
        JSONObject jsonObject = JSONObject.parseObject(game_goods_attr).getJSONObject("data");
        List<JSONObject> data_obj = JSONObject.parseArray(jsonObject.getString("data_array"), JSONObject.class);
        for (JSONObject data : data_obj) {
            if (type.contains(data.getString("type"))) {
                InterAttrRes interServerRes = new InterAttrRes();
                interServerRes.setId(data.getString("id"));
                interServerRes.setName(data.getString("attr_name"));
                if (StringUtils.equals(data.getString("type"), "radio") || StringUtils.equals(data.getString("type"), "select")) {
                    List<JSONObject> attr_value_list = JSONObject.parseArray(data.getString("attr_value"), JSONObject.class);
                    List<InterAttrRes> childrenList = new ArrayList<>();
                    for (JSONObject serverJson : attr_value_list) {
                        InterAttrRes children = new InterAttrRes();
                        children.setId(serverJson.getString("id"));
                        children.setName(serverJson.getString("name"));
                        childrenList.add(children);
                    }
                    interServerRes.setInterServerRes(childrenList);
                }
                if (data.getInteger("is_must") == 1) {
                    interServerRes.setRequired(true);
                }
                resultList.add(interServerRes);
            }
        }
        return resultList;
    }

    /**
     * 构建请求
     *
     * @param name   请求后缀名称
     * @param params 请求参数
     * @return 请求结果
     */
    public String post(String name, TreeMap<String, Object> params, SalePartner salePartner) {
        Long timestamp = System.currentTimeMillis() / 1000;
        // 获取签名
        String signature = signature(params, timestamp, salePartner);
        String ret;
        // 获取请求链接
        String url = getUrl(name, signature, timestamp, salePartner);
        String body = JSONUtil.toJsonStr(params);
        // 0:签名并加密 1:只签名
        if (debug == 1) {
            ret = postRaw(url, body);
        } else {
            ret = postRaw(url, aesEncode(body, salePartner));
            ret = aesDecode(ret, salePartner);
        }
        return ret;
    }

    /**
     * 发送 post 请求
     *
     * @param url  请求地址
     * @param body 请求参数
     * @return
     */
    public String postRaw(String url, String body) {
        return HttpRequest.post(url)
                .header(Header.USER_AGENT, userAgent)//头信息，多个头信息多次调用此方法即可
                .body(body)
                .timeout(timeout)
                .execute().body();
    }

    /**
     * 获取请求地址
     *
     * @param name      请求后缀名
     * @param signature 签名
     * @param timestamp 时间戳
     * @return 请求链接
     */
    public String getUrl(String name, String signature, Long timestamp, SalePartner salePartner) {
        return BASE_URL + name + "?app_id=" + salePartner.getOther() + "&timestamp=" + timestamp + "&sign=" + signature + "&debug=" + debug;
    }

    /**
     * 获取签名
     *
     * @param params    请求参数
     * @param timestamp 时间戳
     * @return
     */
    public String signature(TreeMap<String, Object> params, Long timestamp, SalePartner salePartner) {
        String urlParams;
        try {
            urlParams = buildQuery(params);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        System.out.println(urlParams);
        return DigestUtil.md5Hex(salePartner.getSaleKey() + urlParams + timestamp + salePartner.getTwoOther()).toUpperCase();
    }

    /**
     * 构建加密请求参数
     *
     * @param data 请求参数
     * @return
     * @throws Exception
     */
    private static String buildQuery(Map<String, Object> data) throws Exception {
        StringBuilder sb = new StringBuilder();
        buildQueryRecursive(data, "", sb);
        // 去除末尾的 &
        String queryString = sb.toString();
        return queryString.replaceAll("&$", "");
    }

    /**
     * 递归构建查询参数，将参数转为 url 编码
     *
     * @param data   请求参数
     * @param prefix 前缀
     * @param sb
     * @throws Exception
     */
    private static void buildQueryRecursive(Map<String, Object> data, String prefix, StringBuilder sb) throws Exception {
        for (Map.Entry<String, Object> entry : data.entrySet()) {
            String key = prefix.isEmpty() ? entry.getKey() : prefix + "[" + entry.getKey() + "]";
            Object value = entry.getValue();
            // 判断类型，如果为 map 则递归操作
            if (value instanceof Map) {
                buildQueryRecursive((Map<String, Object>) value, key, sb);
            } else if (value instanceof List) {
                for (int i = 0; i < ((List<?>) value).size(); i++) {
                    buildQueryRecursive(Collections.singletonMap(String.valueOf(i), ((List<?>) value).get(i)), key, sb);
                }
            } else {
                sb.append(URLEncoder.encode(key, "UTF-8")).append("=");
                if (value instanceof Boolean) {
                    sb.append((boolean) value ? 1 : 0);
                } else if (value instanceof BigDecimal) {
                    // 去掉末尾零并避免科学计数法
                    String result = ((BigDecimal) value).stripTrailingZeros().toPlainString();
                    sb.append(URLEncoder.encode(result, "UTF-8"));
                } else if (value instanceof Number) {
                    // 处理 Double/Float 等类型
                    String text = value.toString();
                    text = removeTrailingZeros(text); // 自定义方法去除末尾零
                    sb.append(URLEncoder.encode(text, "UTF-8"));
                } else {
                    sb.append(URLEncoder.encode(value.toString(), "UTF-8"));
                }
                sb.append("&");
            }
        }
    }

    /**
     * 去除数字字符串末尾的零（适用于 Double/Float 转换后的字符串）
     *
     * @param input
     * @return
     */
    private static String removeTrailingZeros(String input) {
        if (input.contains(".")) {
            // 删除小数点后无效的零
            input = input.replaceAll("0+$", ""); // 删除末尾连续的零
            // 如果小数点后全为零，则删除小数点
            if (input.endsWith(".")) {
                input = input.substring(0, input.length() - 1);
            }
        }
        return input;
    }

    /**
     * 将参数转为 url 编码，并转为 Base64 格式
     *
     * @param str 请求参数 json 字符串
     * @return
     */
    private String aesEncode(String str, SalePartner salePartner) {
        byte[] encrypted = new byte[0];
        try {
            encrypted = AESUtil.encrypt(str.getBytes(), salePartner.getSaleKey());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return Base64.getEncoder().encodeToString(encrypted);
    }

    /**
     * 将加密参数进行解密
     *
     * @param hex 返回的结果
     * @return 解密后的结果
     */
    private String aesDecode(String hex, SalePartner salePartner) {
        try {
            byte[] base64 = Base64.getMimeDecoder().decode(hex);
            return AESUtil.decrypt(base64, salePartner.getSaleKey());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
